/*
 * uCharts®
 * 高性能跨平台图表库，支持H5、APP、小程序（微信/支付宝/百度/头条/QQ/360）、Vue、Taro等支持canvas的框架平台
 * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
 * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 * 复制使用请保留本段注释，感谢支持开源！
 * 
 * uCharts®官方网站
 * https://www.uCharts.cn
 * 
 * 开源地址:
 * https://gitee.com/uCharts/uCharts
 * 
 * uni-app插件市场地址：
 * http://ext.dcloud.net.cn/plugin?id=271
 * 
 */

'use strict';

var config = {
    type: 'line',
    categories: [],
    series: [{
        name: "成交量A",
        data: []
    }],
    yAxis: {
        gridType: 'dash',
        dashLength: 2,
    },
    xAxis: {
        disableGrid: true,
    },
    extra: {
        line: {
            type: 'straight',
            width: 2
        },
    }
};

var option = {
    type: 'line',
    canvasId: '',
    canvas2d: false,
    background: 'none',
    animation: true,
    timing: 'easeOut',
    duration: 1000,
    color: ['#7B68EE', '#5AB1EF', '#FFB980', '#B6A2DE', '#2EC7C9', '#E882E8', '#91CA8C', '#F49F42'],
    padding: [15, 15, 0, 15],
    rotate: false,
    rotateLock: false,
    fontSize: 13,
    fontColor: '#666666',
    dataLabel: false,
    dataPointShape: true,
    dataPointShapeType: 'solid',
    touchMoveLimit: 60,
    enableScroll: false,
    enableMarkLine: false,
    legend: {
        show: true,
        position: 'bottom',
        float: 'center',
        padding: 5,
        margin: 5,
        backgroundColor: 'rgba(0,0,0,0)',
        borderColor: 'rgba(0,0,0,0)',
        borderWidth: 0,
        fontSize: 13,
        fontColor: '#666666',
        lineHeight: 11,
        hiddenColor: '#CECECE',
        itemGap: 10
    },
    xAxis: {
        disableGrid: false,
        gridType: 'solid',
        gridColor: '#CCCCCC',
        gridEval: 1,
        calibration: false,
        fontColor: '#666666',
        fontSize: 13,
        rotateLabel: false,
        rotateAngle: 45,
        labelCount: 5,
        boundaryGap: 'center',
        axisLine: true,
        axisLineColor: '#CCCCCC'
    },
    yAxis: {
        disabled: false,
        disableGrid: false,
        splitNumber: 5,
        gridType: 'solid',
        gridColor: '#CCCCCC',
        gridEval: 1,
        padding: 10,
        showTitle: false,
        data: []
    },
    extra: {
        line: {
            type: 'straight',
            width: 2
        },
        tooltip: {
            showBox: true,
            showArrow: true,
            showCategory: false,
            borderWidth: 0,
            borderRadius: 0,
            borderColor: '#000000',
            borderOpacity: 0.7,
            bgColor: '#000000',
            bgOpacity: 0.7,
            gridType: 'solid',
            dashLength: 4,
            gridColor: '#CCCCCC',
            fontColor: '#FFFFFF',
            splitLine: true,
            horizentalLine: false,
            xAxisLabel: false,
            yAxisLabel: false,
            labelBgColor: '#FFFFFF',
            labelBgOpacity: 0.7,
            labelFontColor: '#666666'
        }
    }
};

function deepClone(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    var result = Array.isArray(obj) ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = deepClone(obj[key]);
        }
    }
    return result;
}

function assign(target, ...varArgs) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
    }
    var to = Object(target);
    for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];
        if (nextSource != null) {
            for (var nextKey in nextSource) {
                if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                    to[nextKey] = nextSource[nextKey];
                }
            }
        }
    }
    return to;
}

var uCharts = function(args) {
    this.opts = assign({}, config, args);
    this.config = assign({}, option, args);
    this.context = uni.createCanvasContext(this.opts.canvasId, this.opts.$this);
    this.chartData = {
        categories: [],
        series: []
    };
    this.event = {
        tapped: {},
        touched: {},
        moved: {},
        legendTapped: {}
    };
};

uCharts.prototype.updateData = function(data = {}) {
    this.opts = assign({}, this.opts, data);
    this.opts.series = data.series || this.opts.series;
    this.opts.categories = data.categories || this.opts.categories;
    this.draw();
};

uCharts.prototype.draw = function() {
    var context = this.context;
    context.clearRect(0, 0, this.opts.width, this.opts.height);
    
    // 绘制坐标轴
    this.drawXAxis();
    this.drawYAxis();
    
    // 绘制数据线
    this.drawLine();
    
    // 绘制图例
    if (this.opts.legend && this.opts.legend.show !== false) {
        this.drawLegend();
    }
    
    context.draw();
};

uCharts.prototype.drawXAxis = function() {
    var context = this.context;
    var opts = this.opts;
    var xAxis = opts.xAxis || {};
    var categories = opts.categories || [];
    
    var startX = this.config.padding[3];
    var endX = this.opts.width - this.config.padding[1];
    var startY = this.opts.height - this.config.padding[2];
    
    // 绘制X轴线
    if (xAxis.axisLine !== false) {
        context.beginPath();
        context.setStrokeStyle(xAxis.axisLineColor || '#CCCCCC');
        context.moveTo(startX, startY);
        context.lineTo(endX, startY);
        context.stroke();
        context.closePath();
    }
    
    // 绘制X轴刻度文字
    if (categories.length > 0) {
        var step = (endX - startX) / (categories.length - 1);
        context.setFontSize(xAxis.fontSize || 13);
        context.setFillStyle(xAxis.fontColor || '#666666');
        categories.forEach((item, index) => {
            var x = startX + index * step;
            context.fillText(item, x - context.measureText(item).width / 2, startY + 20);
        });
    }
};

uCharts.prototype.drawYAxis = function() {
    var context = this.context;
    var opts = this.opts;
    var yAxis = opts.yAxis || {};
    
    var startX = this.config.padding[3];
    var startY = this.opts.height - this.config.padding[2];
    var endY = this.config.padding[0];
    
    // 绘制Y轴线
    context.beginPath();
    context.setStrokeStyle(yAxis.axisLineColor || '#CCCCCC');
    context.moveTo(startX, startY);
    context.lineTo(startX, endY);
    context.stroke();
    context.closePath();
    
    // 计算Y轴刻度
    var series = opts.series || [];
    if (series.length > 0) {
        var values = [];
        series.forEach(item => {
            values = values.concat(item.data);
        });
        var max = Math.max(...values);
        var min = Math.min(...values);
        var step = (max - min) / (yAxis.splitNumber || 5);
        
        // 绘制Y轴刻度和网格
        for (var i = 0; i <= yAxis.splitNumber; i++) {
            var y = startY - (i / yAxis.splitNumber) * (startY - endY);
            var value = min + i * step;
            
            // 绘制刻度文字
            context.setFontSize(yAxis.fontSize || 13);
            context.setFillStyle(yAxis.fontColor || '#666666');
            context.fillText(value.toFixed(0), startX - 25, y + 6);
            
            // 绘制网格线
            if (yAxis.gridType === 'dash') {
                var dashLen = yAxis.dashLength || 4;
                for (var j = startX; j < this.opts.width - this.config.padding[1]; j += dashLen * 2) {
                    context.beginPath();
                    context.setStrokeStyle(yAxis.gridColor || '#CCCCCC');
                    context.moveTo(j, y);
                    context.lineTo(j + dashLen, y);
                    context.stroke();
                    context.closePath();
                }
            } else {
                context.beginPath();
                context.setStrokeStyle(yAxis.gridColor || '#CCCCCC');
                context.moveTo(startX, y);
                context.lineTo(this.opts.width - this.config.padding[1], y);
                context.stroke();
                context.closePath();
            }
        }
    }
};

uCharts.prototype.drawLine = function() {
    var context = this.context;
    var opts = this.opts;
    var series = opts.series || [];
    
    var startX = this.config.padding[3];
    var startY = this.opts.height - this.config.padding[2];
    var endY = this.config.padding[0];
    
    series.forEach((item, index) => {
        var data = item.data || [];
        if (data.length > 0) {
            // 计算数据点位置
            var points = [];
            var xStep = (this.opts.width - this.config.padding[1] - this.config.padding[3]) / (data.length - 1);
            var yRange = Math.max(...data) - Math.min(...data);
            var yStep = yRange > 0 ? (startY - endY) / yRange : 0;
            
            data.forEach((value, i) => {
                var x = startX + i * xStep;
                var y = startY - (value - Math.min(...data)) * yStep;
                points.push([x, y]);
            });
            
            // 绘制线条
            context.beginPath();
            context.setStrokeStyle(this.config.color[index]);
            context.setLineWidth(opts.extra.line.width || 2);
            points.forEach((point, i) => {
                if (i === 0) {
                    context.moveTo(point[0], point[1]);
                } else {
                    context.lineTo(point[0], point[1]);
                }
            });
            context.stroke();
            context.closePath();
            
            // 绘制数据点
            if (opts.dataPointShape) {
                points.forEach(point => {
                    context.beginPath();
                    context.setFillStyle(this.config.color[index]);
                    context.arc(point[0], point[1], 3, 0, 2 * Math.PI);
                    context.fill();
                    context.closePath();
                });
            }
            
            // 绘制数据标签
            if (opts.dataLabel) {
                context.setFontSize(this.config.fontSize);
                context.setFillStyle(this.config.fontColor);
                points.forEach((point, i) => {
                    var value = data[i].toString();
                    var metrics = context.measureText(value);
                    context.fillText(value, point[0] - metrics.width / 2, point[1] - 10);
                });
            }
        }
    });
};

uCharts.prototype.drawLegend = function() {
    var context = this.context;
    var opts = this.opts;
    var series = opts.series || [];
    var legend = opts.legend || {};
    
    if (series.length > 0) {
        var startY = this.opts.height - 30;
        var startX = this.config.padding[3];
        var itemWidth = 15;
        var itemGap = legend.itemGap || 10;
        
        series.forEach((item, index) => {
            // 绘制图例标记
            context.beginPath();
            context.setFillStyle(this.config.color[index]);
            context.rect(startX, startY, itemWidth, itemWidth);
            context.fill();
            context.closePath();
            
            // 绘制图例文字
            context.setFontSize(legend.fontSize || 13);
            context.setFillStyle(legend.fontColor || '#666666');
            context.fillText(item.name, startX + itemWidth + 5, startY + itemWidth - 2);
            
            startX += itemWidth + context.measureText(item.name).width + itemGap + 5;
        });
    }
};

export default uCharts; 